package com.zmn.oms.business.impl.work.tag;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.common.data.common.dro.tags.TagsDRO;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.base.pilot.common.dto.pilot.PilotCheckQuery;
import com.zmn.base.pilot.common.enums.PilotTypeEnum;
import com.zmn.base.pilot.dubbo.interfaces.pilot.PilotRemoteService;
import com.zmn.base.product.common.consts.BaseProductConsts;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.manager.mq.constant.MqTopicConsts;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.oms.business.interfaces.base.BaseCodeService;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.business.interfaces.eventsnotice.EventsNoticeBService;
import com.zmn.oms.business.interfaces.order.DuplicateOrderBService;
import com.zmn.oms.business.interfaces.refund.OrderRefundBService;
import com.zmn.oms.business.interfaces.remark.OrderRemarkBService;
import com.zmn.oms.business.interfaces.work.OrderWorkRelationBService;
import com.zmn.oms.business.interfaces.work.tag.OrderTagBService;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dio.redistribute.DoingDuplicateOrderDIO;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.model.dto.tag.OrderTagAddDTO;
import com.zmn.oms.model.dto.tag.OrderTagDTO;
import com.zmn.oms.model.dto.tag.OrderTagDelDTO;
import com.zmn.oms.model.entity.advancequote.AdvanceQuoteOpenQuery;
import com.zmn.oms.model.entity.changerecord.OrderChangeRecord;
import com.zmn.oms.model.entity.conf.ordertag.ConfOrderTag;
import com.zmn.oms.model.entity.conf.ordertag.ConfOrderTagQuery;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.quotation3.OrderQuotationProcess;
import com.zmn.oms.model.entity.tag.OrderTag;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.model.entity.work.OrderWorkRelation;
import com.zmn.oms.model.vo.remark.OrderRemarkVO;
import com.zmn.oms.services.interfaces.changerecord.OrderChangeRecordService;
import com.zmn.oms.services.interfaces.conf.ordertag.ConfOrderTagService;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.orderencrypt.OrderEncryptService;
import com.zmn.oms.services.interfaces.quotation3.OrderQuotationProcessService;
import com.zmn.oms.services.interfaces.tag.OrderTagService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.pay.common.constant.PayConsts;
import com.zmn.ums.common.chs.dro.user.UserTagInfoDRO;
import com.zmn.ums.dubbo.interfaces.user.UserTagInfoListRemoteService;
import com.zmn.uuc.common.dro.user.UserDetailDRO;
import com.zmn.uuc.dubbo.interfaces.user.UserListRemoteService;
import com.zmn.vas.common.dro.member.MemberDRO;
import com.zmn.vas.dubbo.interfaces.member.MemberListRemoteService;
import com.zmn.xno.dubbo.interfaces.XnoRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SourceFilter;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author sunlife
 * @date:2021/8/18 10:54 上午
 * description:
 */
@Slf4j
@Service
public class OrderTagBServiceImpl implements OrderTagBService {

    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderTagService orderTagService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private ConfOrderTagService confOrderTagService;
    @Autowired
    private OrderQuotationProcessService orderQuotationProcessService;
    @Autowired
    private OrderRefundBService orderRefundBService;
    @Autowired
    private OrderWorkRelationBService orderWorkRelationBService;
    @Autowired
    private EventsNoticeBService eventsNoticeBService;
    @Resource
    private BaseCodeService baseCodeService;

    @Autowired
    private OrderWorkEsBService orderWorkEsBService;
    @Autowired
    private OrderChangeRecordService orderChangeRecordService;
    @Autowired
    private DuplicateOrderBService duplicateOrderBService;
    @Resource
    private OrderEncryptService orderEncryptService;
    @Autowired
    private OrderRemarkBService orderRemarkBService;

    @Resource
    ZmnMQSender zmnMQSender;

    @DubboReference(version = com.zmn.ums.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false, timeout = 2000)
    private UserTagInfoListRemoteService userTagInfoListRemoteService;
    @DubboReference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private PilotRemoteService pilotRemoteService;
    @DubboReference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private UserListRemoteService userListRemoteService;
    @DubboReference(version = com.zmn.vas.dubbo.consts.VasDubboConsts.INTERFACE_VERSION, check = false)
    private MemberListRemoteService memberListRemoteService;

    @DubboReference(version = com.zmn.xno.common.constant.SystemConstants.DUBBO_CONSTS_INTERFACE_VERSION, check = false)
    private XnoRemoteService xnoRemoteService;

    /**
     * 同步订单标签信息
     *
     * @param orderId 订单号
     * @param workId  工单号
     */
    @Override
    public void modifyOrderTagByLogType(Long orderId, Long workId, Integer logType) {
        // 查询工单信息
        OrderWork orderWork = orderWorkService.findOrderWorkByKeySrcMaster(orderId, workId);
        if (Objects.isNull(orderWork)) {
            return;
        }

        // 查询工单标签信息
        List<OrderTag> orderTags = orderTagService.listOrderTagByOrderId(orderId, workId);
        Map<Integer, OrderTag> tagMap = orderTags.stream().collect(Collectors.toMap(OrderTag::getTagId, e -> e, (v1, v2) -> v1));

        // 查询工单详情信息
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKeySrcMaster(orderId);

        // 标记配置
        List<ConfOrderTag> confOrderTagList = confOrderTagService.listByQuery(ConfOrderTagQuery.builder().build());
        if (log.isDebugEnabled()) {
            log.debug("[{}]查询订单标签配置：【{}】", orderWork.getOrderId(), JSON.toJSONString(confOrderTagList));
        }
        Map<Integer, ConfOrderTag> confOrderTagMap = confOrderTagList.stream().collect(Collectors.toMap(ConfOrderTag::getId, item -> item, (k1, k2) -> k1));

        List<Integer> delTagList = Lists.newArrayList();
        List<OrderTag> addTagList = Lists.newArrayList();

        // 会员
        this.setOrderVasMemberTag(delTagList, addTagList, orderWork, orderDetail, tagMap, logType, confOrderTagMap);

        // 用户标签
        this.setUserTag(delTagList, addTagList, orderWork, orderDetail, tagMap, logType, confOrderTagMap, false);

        // 提前付
        this.setAdvancePayTag(delTagList, addTagList, orderWork, orderDetail, tagMap, logType, confOrderTagMap);

        // 3min内取消
        this.setCancelOrderWithin3Minutes(addTagList, orderWork, logType, confOrderTagMap);

        // 过保新单
        this.setRefurbishmentNewOrder(delTagList, addTagList, orderWork, orderDetail, tagMap, logType, confOrderTagMap);

        // 返修新单
        this.setReworkNewOrder(delTagList, addTagList, orderWork, orderDetail, tagMap, logType, confOrderTagMap);

        // 测试单
        this.setTestOrder(delTagList, addTagList, orderWork, tagMap, logType, confOrderTagMap);

        // 重复单
        this.setDuplicateOrder(addTagList, orderWork, tagMap, logType, confOrderTagMap);

        // 标记有效/无效联系标签 处理
        this.setContactTag(delTagList, addTagList, orderWork, orderDetail, tagMap, logType, confOrderTagMap);

        // 计价器3.0有效使用
        this.setQuotationThreeValid(delTagList, addTagList, orderWork, logType, confOrderTagMap);

        // 计价器3.0成功单有效使用
        this.setQuotationThreeSuccessValid(addTagList, orderWork, logType, confOrderTagMap);

        // 一口价有效使用标签
        this.setFinalPriceValid(delTagList, addTagList, orderWork, logType, confOrderTagMap);

        // 原路退标签处理
        this.setSupportBacktrackingTag(addTagList, orderWork, logType, confOrderTagMap);

        // 退差额标签处理
        this.setRefundDifferenceTag(addTagList, orderWork, logType, tagMap, confOrderTagMap);

        // 在途重复
        this.setOnServiceDuplicateOrder(delTagList, addTagList, orderWork, orderDetail, logType, tagMap, confOrderTagMap);

        // 优质订单
        this.setHighQualityOrder(delTagList, addTagList, orderWork, orderDetail, logType, tagMap, confOrderTagMap, false);

        // 无网格
        this.setNonGridTag(delTagList, addTagList, orderWork, orderDetail, logType, tagMap, confOrderTagMap, false);

        // 相似当日派处理
        this.setSimilarDistributeTag(delTagList, addTagList, orderWork, orderDetail, logType, tagMap, confOrderTagMap);

        // 疫情无法服务处理
        this.setEpidemicUnserviceableCancel(addTagList, orderWork, logType, confOrderTagMap);

        // 报价未确认
        this.processQuoteUnConfirm(delTagList, addTagList, orderWork, logType, confOrderTagMap, tagMap);

        if (CollectionUtil.isNotNullOrEmpty(delTagList)) {
            OrderTagDelDTO orderTagDTO = new OrderTagDelDTO();
            orderTagDTO.setOrderId(orderId);
            orderTagDTO.setWorkId(workId);
            orderTagDTO.setOrderTagIdList(delTagList);
            orderTagService.deleteOrderTagByTagIdList(orderTagDTO);
        }

        if (CollectionUtil.isNotNullOrEmpty(addTagList)) {
            OrderTagDTO orderTagDTO = new OrderTagDTO();
            orderTagDTO.setOrderId(orderId);
            orderTagDTO.setWorkId(workId);
            orderTagDTO.setOrderTagList(addTagList);
            orderTagService.saveOrderTagList(orderTagDTO);
        }

        // 如果标签发生变动发送tag的通用消息
        if (CollectionUtil.isNotNullOrEmpty(delTagList) || CollectionUtil.isNotNullOrEmpty(addTagList)) {
            OrderTagDTO orderTagDTO = new OrderTagDTO();
            orderTagDTO.setOrderId(orderId);
            orderTagDTO.setWorkId(workId);
            this.sendOrderTagNotice(orderTagDTO);
        }
    }

    /**
     * 发送tag的通用消息
     * @param orderTagDTO
     */
    private void sendOrderTagNotice(OrderTagDTO orderTagDTO) {
        // 节点通知--通用订阅
        OrderLog orderLog = new OrderLog();
        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_ORDER_WORK_TAG);
        orderLog.setOperator("系统");
        orderLog.setOperatorId(1L);
        orderLog.setOperatorType(com.zmn.consts.GlobalConsts.OPERATE_USER_TYPE_SYSTEM);
        eventsNoticeBService.notice(orderLog, null, null, null, orderTagDTO, null);
    }

    /**
     * 类描述：原路退标签处理
     *
     * @author  liuying
     * @date   2022/02/23 11:59
     */
    private void setSupportBacktrackingTag(List<OrderTag> addTags, OrderWork orderWork, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        if (!Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_COMPLETE)) {
            return;
        }

        // 只处理新单
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        try {
            boolean supportBacktracking = orderRefundBService.supportBacktracking(orderWork.getOrderId());
            if(!supportBacktracking){
                return;
            }
            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_WORK_SUPPORT_BACKTRACKING);
            if (Objects.isNull(confOrderTag)) {
                return;
            }
            addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("保存标签[原路退类型]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 类描述：退差额标签处理
     *
     * @author liuying
     * @date 2022/02/23 11:59
     */
    private void setRefundDifferenceTag(List<OrderTag> addTags, OrderWork orderWork, Integer logType, Map<Integer, OrderTag> tagMap, Map<Integer, ConfOrderTag> confOrderTagMap) {
        if (!Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_REFUND_DIFFERENCE)) {
            return;
        }

        // 只处理新单
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        // 已经有此标签了
        OrderTag orderTag = tagMap.get(OrderTagConsts.TAG_ID_ORDER_REFUND_DIFFERENCE);
        if (Objects.nonNull(orderTag)) {
            return;
        }

        try {
            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_ORDER_REFUND_DIFFERENCE);
            if (Objects.isNull(confOrderTag)) {
                return;
            }
            addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("保存标签[原路退类型]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 类描述：在途重复订单标签
     *
     * @author sunlife
     * @date 2022/06/07 17:29
     */
    private void setOnServiceDuplicateOrder(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Integer logType, Map<Integer, OrderTag> tagMap, Map<Integer, ConfOrderTag> confOrderTagMap) {
        if (!(Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_INPUT) || Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_UPDATE))) {
            return;
        }

        // 只处理新单
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_ON_SERVICE_DUPLICATE);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        try {
            // 查询在途重复单
            // 任一电话匹配
            List<String> phoneList = Lists.newArrayList(orderDetail.getTelephone());
            if (StringUtils.isNotBlank(orderDetail.getTelephone2())) {
                phoneList.add(orderDetail.getTelephone2());
            }
            if (StringUtils.isNotBlank(orderDetail.getTelephone3())) {
                phoneList.add(orderDetail.getTelephone3());
            }
            // 校验在途重复
            DoingDuplicateOrderDIO doingDuplicateOrderDIO = new DoingDuplicateOrderDIO();
            doingDuplicateOrderDIO.setWorkId(orderWork.getWorkId());
            doingDuplicateOrderDIO.setPhoneList(phoneList);
            doingDuplicateOrderDIO.setServProductGroupId(orderWork.getServProductGroupId());
            doingDuplicateOrderDIO.setLatitude(orderDetail.getLatitude());
            doingDuplicateOrderDIO.setLongitude(orderDetail.getLongitude());
            Long doingDuplicateOrderId = duplicateOrderBService.findDoingDuplicateOrderId(doingDuplicateOrderDIO);
            if (Objects.nonNull(doingDuplicateOrderId) && !tagMap.containsKey(OrderTagConsts.TAG_ID_ON_SERVICE_DUPLICATE)) {
                log.info("订单[{}] 在途重复单ID：{}", orderWork.getWorkId(), doingDuplicateOrderId);
                // 没有在途重复标签，添加
                addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
            } else if (tagMap.containsKey(OrderTagConsts.TAG_ID_ON_SERVICE_DUPLICATE)) {
                delTags.add(OrderTagConsts.TAG_ID_ON_SERVICE_DUPLICATE);
            }
        } catch (Exception e) {
            log.error("保存标签[原路退类型]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 类描述：优质订单标签
     *
     * @param autoFlow 是否自动流转
     * @author sunlife
     * @date 2022/06/07 17:29
     */
    private void setHighQualityOrder(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork,
                                     OrderDetail orderDetail, Integer logType, Map<Integer, OrderTag> tagMap,
                                     Map<Integer, ConfOrderTag> confOrderTagMap, boolean autoFlow) {
        // 不是自动流转
        if (!autoFlow) {
            boolean isUpdateTag = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_UPDATE, logType)
                    || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONFIRM, logType);
            if (!isUpdateTag) {
                return;
            }
        }

        // 只处理新单
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_HIGH_QUALITY);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        try {
            OrderTag orderTag = tagMap.get(OrderTagConsts.TAG_ID_HIGH_QUALITY);
            // 获取优质订单渠道配置
            List<TagsDRO> list = baseCodeService.listBaseCodeMap(GlobalConsts.PLAT_MARK_ZMN, OrderConsts.BASE_CODE_MAP_ONE_TYPE_HIGH_QUALITY, orderWork.getChannelId(), null);

            if (Objects.isNull(orderTag)) {
                if (CollectionUtil.isNotNullOrEmpty(list)) {
                    addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
                }
            } else {
                if (CollectionUtil.isNullOrEmpty(list)) {
                    delTags.add(OrderTagConsts.TAG_ID_HIGH_QUALITY);
                }
            }
        } catch (Exception e) {
            log.error("保存标签[优质订单]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 类描述：无网格标签
     *
     * @author wangxiaokun
     * @date 2022/07/26 17:29
     */
    private void setNonGridTag(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Integer logType, Map<Integer, OrderTag> tagMap, Map<Integer, ConfOrderTag> confOrderTagMap, boolean autoFlow) {

        // 不是自动流转只处理修改
        if (!autoFlow) {
            boolean isUpdateTag = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_UPDATE, logType)
                    || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONFIRM, logType);
            if (!isUpdateTag) {
                return;
            }
        }

        // 只处理新单
        if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
            return;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_NON_GRID);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        try {
            OrderTag orderTag = tagMap.get(OrderTagConsts.TAG_ID_NON_GRID);

            // 是否平台直派，没有网格id
            boolean isNonGrid = Objects.equals(orderWork.getDistributeWay(), OrderDistributeConsts.DISTRIBUTE_WAY_PLAT)
                    && Objects.equals(orderDetail.getGridId(), GlobalConsts.NONE);

            // 订单当前没有无网格标签，但是符合条件就新增
            if (Objects.isNull(orderTag)) {
                if (isNonGrid) {
                    addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
                }
            } else {
                // 订单当前没有无网格标签，但是不符合条件就删除
                if (!isNonGrid) {
                    delTags.add(OrderTagConsts.TAG_ID_NON_GRID);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("保存标签[无网格]异常：[{}]", e.getMessage());
        }
    }

    /**
         * 有效、无效联系标签处理
         *
         * @param delTags
         * @param addTags
         * @param orderWork
         * @param orderDetail
         * @param tagMap
         * @param logType
         */
    private void setContactTag(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Map<Integer, OrderTag> tagMap, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {

        // 派单节点，删除标签
        if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE, logType)) {
            delTags.add(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE);
            delTags.add(OrderTagConsts.TAG_ID_WORK_CONTACT_INVALID);
            delTags.add(OrderTagConsts.TAG_ID_WARNING_CONTACT_TIMEOUT);
            return;
        }

        // 取消节点，如果未派单需要删除 有效、无效联系 标记
        if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, logType) && NumberUtil.isNullOrZero(orderWork.getMasterId())) {
            delTags.add(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE);
            delTags.add(OrderTagConsts.TAG_ID_WORK_CONTACT_INVALID);
            return;
        }

        // 只处理  联系、完成、取消节点
        boolean isProcessLogType = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER, logType) ||
                Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, logType) || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_COMPLETE, logType);
        if (!isProcessLogType) {
            return;
        }

        // 已经标记有效，不处理
        if (tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE)) {
            return;
        }

        try {

            // 工程师联系用户节点处理
            this.processContactTagAtContactUser(delTags, addTags, orderWork, orderDetail, tagMap, logType, confOrderTagMap);

            // 同一个工程师相同的号码是否已经联系过，标记有效
            this.processContactTagAtExistContactEffectiveTag(delTags, addTags, orderWork, orderDetail, tagMap, logType, confOrderTagMap);

            // 小号失效，标记有效
            this.processContactTagAtBindXnoStatus(delTags, addTags, orderWork, orderDetail, tagMap, logType, confOrderTagMap);

            // 工单完成或取消节点处理
            this.processContactTagAtCancelOrFinish(delTags, addTags, orderWork, orderDetail, tagMap, logType, confOrderTagMap);
            // 设置有效标签标记时间
            if (tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE)) {
                if(Objects.nonNull(tagMap.get(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE))){
                    tagMap.get(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE).setCreateTime(orderWork.getContactTime());
                }
            }
        } catch (Exception e) {
            log.error("保存用户标签[提前付]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 工程师联系用户节点 处理 有效、无效联系
     *
     * @param delTags
     * @param addTags
     * @param orderWork
     * @param orderDetail
     * @param tagMap
     * @param logType
     * @param confOrderTagMap
     */
    private void processContactTagAtContactUser(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Map<Integer, OrderTag> tagMap, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        /**
         * 业务规则
         * 工程师加单，渠道 = 工程师推荐A/B ,领单工程师 = 加单工程师
         * 联系用户时候判断是否绑定小号，若无小号，直接有效联系。
         * 若有小号，查询通话记录，若满足需求，则有效联系。
         */
        if (!Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER, logType)) {
            return;
        }

        Integer contactTagId = null;

        // 没有绑定小号，标记有效联系
        if (StringUtils.isBlank(orderDetail.getBindTelephone()) &&
                StringUtils.isBlank(orderDetail.getBindTelephone2()) &&
                StringUtils.isBlank(orderDetail.getBindTelephone3())) {
            contactTagId = OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE;
        }

        // 工程师推荐，标记有效
        if (Objects.nonNull(orderWork.getRecommenderId()) &&
                Objects.equals(orderWork.getRecommenderType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)
                && Objects.equals(orderWork.getRecommenderId().intValue(), orderWork.getMasterId())) {
            contactTagId = OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE;
        }

        if (Objects.isNull(contactTagId)) {
            return;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(contactTagId);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        OrderTag orderTag = this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag);
        addTags.add(orderTag);
        tagMap.put(contactTagId, orderTag);
    }

    /**
     * 完成、取消节点 处理 有效、无效联系
     *
     * @param delTags
     * @param addTags
     * @param orderWork
     * @param orderDetail
     * @param tagMap
     * @param logType
     * @param confOrderTagMap
     */
    private void processContactTagAtCancelOrFinish(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Map<Integer, OrderTag> tagMap, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        boolean isProcessLogType = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, logType) || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_COMPLETE, logType);
        if (!isProcessLogType) {
            return;
        }

        // 工程师未联系的，不标记
        if (Objects.isNull(orderWork.getContactTime())) {
            return;
        }

        // 已标记不处理
        if (tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE) || tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_CONTACT_INVALID)) {
            return;
        }

        // 处理没有标记的情况
        Integer contactTagId = OrderTagConsts.TAG_ID_WORK_CONTACT_INVALID;

        // 没有绑定小号，标记有效联系
        if (StringUtils.isBlank(orderDetail.getBindTelephone()) &&
                StringUtils.isBlank(orderDetail.getBindTelephone2()) &&
                StringUtils.isBlank(orderDetail.getBindTelephone3())) {
            contactTagId = OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE;
        }

        // 工程师推荐，标记有效
        if (Objects.nonNull(orderWork.getRecommenderId()) &&
                Objects.equals(orderWork.getRecommenderType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)
                && Objects.equals(orderWork.getRecommenderId().intValue(), orderWork.getMasterId())) {
            contactTagId = OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(contactTagId);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        OrderTag orderTag = this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag);
        addTags.add(orderTag);
        tagMap.put(contactTagId, orderTag);
    }

    /**
     * 同一个工程师相同的号码是否已经联系过，标记有效
     *
     * @param delTags
     * @param addTags
     * @param orderWork
     * @param orderDetail
     * @param tagMap
     * @param logType
     * @param confOrderTagMap
     */
    private void processContactTagAtExistContactEffectiveTag(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Map<Integer, OrderTag> tagMap, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        boolean isProcessLogType = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, logType) || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_COMPLETE, logType) ||
                Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER, logType);
        if (!isProcessLogType) {
            return;
        }

        // 已标记不处理
        if (tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE) || tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_CONTACT_INVALID)) {
            return;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        // 相同的号码是否已经联系过
        boolean existContactEffectiveTag = this.existContactEffectiveTagOrderByExcludeOrderId(orderWork, orderDetail);
        if(!existContactEffectiveTag){
            return;
        }

        OrderTag orderTag = this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag);
        addTags.add(orderTag);
        tagMap.put(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE, orderTag);
    }

    private void processContactTagAtBindXnoStatus(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Map<Integer, OrderTag> tagMap, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        boolean isProcessLogType = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, logType) || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_COMPLETE, logType) ||
                Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONTACT_USER, logType);
        if (!isProcessLogType) {
            return;
        }

        // 已标记不处理
        if (tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE) || tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_CONTACT_INVALID)) {
            return;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        // 是否绑定小号
        if (StringUtils.isBlank(orderDetail.getBindTelephone())) {
            return;
        }

        // 查询小号状态
        ResponseDTO<Boolean> booleanResponseDTO = xnoRemoteService.queryExposeByXno(orderDetail.getBindTelephone());
        Boolean dtoData = booleanResponseDTO.getData();
        if (!Objects.equals(dtoData, true)) {
            return;
        }

        log.info("小号显示真实号码，工单标记有效：{}", orderWork.getWorkId());
        OrderTag orderTag = this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag);
        addTags.add(orderTag);
        tagMap.put(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE, orderTag);
    }


    /**
     * 会员单
     *
     * @param delTags
     * @param addTags
     * @param orderWork
     * @param orderDetail
     * @param tagMap
     * @param logType
     */
    private void setOrderVasMemberTag(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Map<Integer, OrderTag> tagMap, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        if (!Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_INPUT)) {
            return;
        }

        if (!Objects.equals(orderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_MEMBER)) {
            return;
        }
        if (orderWork.getUserId() == null || orderWork.getUserId() == 0L) {
            return;
        }

        try {
            ResponseDTO<UserDetailDRO> userDetailDROResponseDTO = userListRemoteService.getUserDetailById(orderWork.getUserId(), false);
            if (userDetailDROResponseDTO.getData() == null || NumberUtil.isNullOrZero(userDetailDROResponseDTO.getData().getPassId())) {
                return;
            }
            log.info("#oms#工单={},是否是会员工单，入参={}", orderWork.getOrderId(), userDetailDROResponseDTO.getData().getPassId());
            ResponseDTO<MemberDRO> memberDROResponseDTO = memberListRemoteService.getMemberById(userDetailDROResponseDTO.getData().getPassId());
            log.info("#oms#工单={},是否是会员工单，出参={}", orderWork.getOrderId(), JSON.toJSONString(memberDROResponseDTO));
            MemberDRO memberDRO = memberDROResponseDTO.getData();
            if (memberDRO == null || !Objects.equals(memberDRO.getStatus(), GlobalConsts.YES)) {
                return;
            }

            // 1:Z+金卡  2 Z+钻卡
            int tagId = 0;
            if (Objects.equals(memberDRO.getMemberLevel(), 1)) {
                tagId = OrderTagConsts.TAG_ID_WORK_VAS_MEMBER_LEVEL_1;
            } else if (Objects.equals(memberDRO.getMemberLevel(), 2)) {
                tagId = OrderTagConsts.TAG_ID_WORK_VAS_MEMBER_LEVEL_2;
            }

            ConfOrderTag confOrderTag = confOrderTagMap.get(tagId);
            if (Objects.isNull(confOrderTag)) {
                return;
            }
            addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("保存用户标签[会员类型]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 设置过保新单标签
     *
     * @param delTagList
     * @param addTagList
     * @param orderWork
     * @param orderDetail
     * @param tagMap
     * @param logType
     * @param confOrderTagMap
     */
    private void setRefurbishmentNewOrder(List<Integer> delTagList,
                                          List<OrderTag> addTagList,
                                          OrderWork orderWork,
                                          OrderDetail orderDetail,
                                          Map<Integer, OrderTag> tagMap,
                                          Integer logType,
                                          Map<Integer, ConfOrderTag> confOrderTagMap) {
        try {
            // 不是啄木鸟平台下单不处理
            if (!Objects.equals(orderWork.getPlat(), GlobalConsts.PLAT_MARK_ZMN)) {
                return;
            }

            // 不是新单不处理
            if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)) {
                return;
            }
            ArrayList<Integer> allowLogList = Lists.newArrayList(OrderLogConsts.ORDER_LOG_TYPE_INPUT, OrderLogConsts.ORDER_LOG_TYPE_UPDATE);
            // 非录单和修改不处理
            if (!allowLogList.contains(logType)) {
                return;
            }
            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_NEW_ORDER_FOR_REPAIR);
            if (Objects.isNull(confOrderTag)) {
                return;
            }


            // 任一电话匹配
            List<String> phoneList = Lists.newArrayList(orderDetail.getTelephone());
            if (StringUtils.isNotBlank(orderDetail.getTelephone2())) {
                phoneList.add(orderDetail.getTelephone2());
            }
            if (StringUtils.isNotBlank(orderDetail.getTelephone3())) {
                phoneList.add(orderDetail.getTelephone3());
            }

            //  下单时间前九十天  DateUtil.dateFormatToString(baseDefer, DateUtil.FORMAT_DEFAULT)
            Date receiveTime = orderWork.getReceiveTime();
            int workRelationTime = -90; // 过保新单时间
            Date baseDefer = DateUtil.getBaseDefer(receiveTime, workRelationTime);

            BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                    // 排除自己
                    .mustNot(QueryBuilders.termQuery("id", orderWork.getWorkId()))
                    .filter(QueryBuilders.termQuery("type", OrderConsts.ORDER_TYPE_NEW))
                    // 前台产品ID
                    .filter(QueryBuilders.termQuery("showProductId", orderWork.getShowProductId()))
                    // 有保修卡
                    .filter(QueryBuilders.termQuery("hasWarrantyCode", true))
                    // 保修时间
                    .filter(QueryBuilders.rangeQuery("warrantyProductMaxExpiredTime").lte(DateUtil.getNowFormatted()))
                    // 下单时间
                    .filter(QueryBuilders.rangeQuery("receiveTime").gte(DateUtil.dateFormatToString(baseDefer, DateUtil.FORMAT_DEFAULT))
                            .lte(DateUtil.dateFormatToString(receiveTime,DateUtil.FORMAT_DEFAULT)))
                    // 联系电话
                    .filter(QueryBuilders.termsQuery("contact.phone", orderEncryptService.encrypt(phoneList)))
                    // 排除过保新单
                    .mustNot(QueryBuilders.termQuery("orderTagList.tagId", OrderTagConsts.TAG_ID_NEW_ORDER_FOR_REPAIR));

            NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
            NativeSearchQuery build = nativeSearchQueryBuilder.withQuery(queryBuilder)
                    .withPageable(PageRequest.of(0, 1, Sort.by(Sort.Order.desc("warrantyProductMaxExpiredTime"))))
                    .build();
            log.info("workId={} 过保新单ES查询人参数：showProductId={}  queryPhone={}", orderWork.getWorkId(), orderWork.getShowProductId(), phoneList);
            FetchSourceFilter fetchSourceFilter = new FetchSourceFilter(new String[]{"id"}, new String[]{});
            build.addSourceFilter(fetchSourceFilter);
            List<EsOrderWork> page = orderWorkEsBService.listPageByQuery(build);
            log.debug("过保新单查询 结果[{}]", JSON.toJSONString(page));
            if (CollectionUtil.isNullOrEmpty(page)) {
                if (Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_UPDATE)) {
                    orderWorkRelationBService.deleteOrderWorkRelationByWorkIdAndType(orderWork.getOrderId(), orderWork.getWorkId(),
                            OrderConsts.WORK_RELATION_TYPE_NEW_INSURANCE_FORM);
                    delTagList.add(OrderTagConsts.TAG_ID_NEW_ORDER_FOR_REPAIR);
                }
                return;
            }

            // 存储过保源单信息
            Date now = DateUtil.getNow();
            Long relationWorkId = page.get(0).getId();
            OrderWorkRelation workRelation = OrderWorkRelation.builder()
                    .orderId(orderWork.getOrderId())
                    .workId(orderWork.getWorkId())
                    .originalWorkId(relationWorkId)
                    .rootWorkId(relationWorkId)
                    .type(OrderConsts.WORK_RELATION_TYPE_NEW_INSURANCE_FORM)
                    .createTime(now)
                    .updateTime(now).build();
            orderWorkRelationBService.addOrderWorkRelation(workRelation);

            // 已经配置过的不需要重复配置了
            boolean exist = tagMap.containsKey(OrderTagConsts.TAG_ID_NEW_ORDER_FOR_REPAIR);
            if (exist) {
                return;
            }

            addTagList.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("workId={} 保存标签[过保新单标签]异常：[{}]", orderWork.getWorkId(), e);
        }
    }

    /**
     * 设置返修新单标签
     *
     * @param delTagList
     * @param addTagList
     * @param orderWork
     * @param orderDetail
     * @param tagMap
     * @param logType
     * @param confOrderTagMap
     */
    private void setReworkNewOrder(List<Integer> delTagList,
                                   List<OrderTag> addTagList,
                                   OrderWork orderWork,
                                   OrderDetail orderDetail,
                                   Map<Integer, OrderTag> tagMap,
                                   Integer logType,
                                   Map<Integer, ConfOrderTag> confOrderTagMap) {
        try {
            // 不是啄木鸟平台下单不处理
            if (!Objects.equals(orderWork.getPlat(), GlobalConsts.PLAT_MARK_ZMN)
                    || !Objects.equals(orderWork.getBizType(), com.zmn.consts.GlobalConsts.BIZ_TYPE_C)) {
                return;
            }

            // 不是返修新单不处理
            if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)
                    || !Objects.equals(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_PLAT_REWORK_NEW_ORDER)
                    || NumberUtil.isNullOrZero(orderWork.getOriginalId())) {
                return;
            }
            ArrayList<Integer> allowLogList = Lists.newArrayList(OrderLogConsts.ORDER_LOG_TYPE_INPUT, OrderLogConsts.ORDER_LOG_TYPE_UPDATE);
            // 非录单和修改不处理
            if (!allowLogList.contains(logType)) {
                return;
            }
            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_NEW_ORDER_FOR_REWORK);
            if (Objects.isNull(confOrderTag)) {
                return;
            }

            boolean exist = tagMap.containsKey(OrderTagConsts.TAG_ID_NEW_ORDER_FOR_REWORK);
            if (exist) {
                return;
            }

            addTagList.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("workId={} 保存标签[返修新单标签]异常：[{}]", orderWork.getWorkId(), e);
        }
    }

    /**
     * 设置测试单标签
     *
     * @param delTagList
     * @param addTagList
     * @param orderWork
     * @param tagMap
     * @param logType
     * @param confOrderTagMap
     */
    private void setTestOrder(List<Integer> delTagList,
                                   List<OrderTag> addTagList,
                                   OrderWork orderWork,
                                   Map<Integer, OrderTag> tagMap,
                                   Integer logType,
                                   Map<Integer, ConfOrderTag> confOrderTagMap) {
        try {
            // 标签配置为空返回
            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_WORK_TEST);
            if (Objects.isNull(confOrderTag)) {
                return;
            }

            // 非录入、确认、修改、取消不处理
            ArrayList<Integer> allowLogList = Lists.newArrayList(OrderLogConsts.ORDER_LOG_TYPE_INPUT,
                    OrderLogConsts.ORDER_LOG_TYPE_UPDATE, OrderLogConsts.ORDER_LOG_TYPE_CONFIRM,
                    OrderLogConsts.ORDER_LOG_TYPE_CANCEL);
            if (!allowLogList.contains(logType)) {
                return;
            }

            // 如果不是测试单需要删除测试标签
            if (!Objects.equals(orderWork.getTest(), com.zmn.consts.GlobalConsts.YES)) {
                delTagList.add(OrderTagConsts.TAG_ID_WORK_TEST);
                return;
            }

            // 是否存在测试单标签
            boolean exist = tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_TEST);
            if (exist) {
                return;
            }

            // 添加测试单标签
            addTagList.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("workId={} 保存标签[测试单标签]异常：[{}]", orderWork.getWorkId(), e);
        }
    }

    /**
     * 设置重复单标签
     *
     * @param addTagList
     * @param orderWork
     * @param tagMap
     * @param logType
     * @param confOrderTagMap
     */
    private void setDuplicateOrder(List<OrderTag> addTagList,
                                   OrderWork orderWork,
                                   Map<Integer, OrderTag> tagMap,
                                   Integer logType,
                                   Map<Integer, ConfOrderTag> confOrderTagMap) {
        try {

            // 非取消节点不处理
            if (!Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_CANCEL)) {
                return;
            }

            // 不是重复不处理
            if (!Objects.equals(orderWork.getDuplicate(), com.zmn.consts.GlobalConsts.YES)) {
                return;
            }

            // 没有配置不处理
            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_WORK_DUPLICATE);
            if (Objects.isNull(confOrderTag)) {
                return;
            }

            // 已存在标签不处理
            boolean exist = tagMap.containsKey(OrderTagConsts.TAG_ID_WORK_DUPLICATE);
            if (exist) {
                return;
            }

            // 添加标签
            addTagList.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("workId={} 保存标签[重复单标签]异常：[{}]", orderWork.getWorkId(), e);
        }
    }

    /**
     * 设置3min内取消标签
     * @param addTags
     * @param orderWork
     * @param logType
     */
    private void setCancelOrderWithin3Minutes(List<OrderTag> addTags, OrderWork orderWork, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        int cancelMinutes = 3;
        try {
            if (!Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, logType)) {
                return;
            }
            // 已领单的，不处理
            if (Objects.nonNull(orderWork.getTakeTime())) {
                return;
            }
            // 未派单和未取消的不处理
            if (Objects.isNull(orderWork.getDistributeTime()) || Objects.isNull(orderWork.getCancelTime())) {
                return;
            }

            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_CANCEL_ORDER_WITHIN_5_MINUTES);
            if (Objects.isNull(confOrderTag)) {
                return;
            }

            // 退单时间
            LocalDateTime cancelTime = LocalDateTime.ofInstant(orderWork.getCancelTime().toInstant(), ZoneId.systemDefault());
            // 派单时间
            LocalDateTime distributeTime = LocalDateTime.ofInstant(orderWork.getDistributeTime().toInstant(), ZoneId.systemDefault());
            if (cancelTime.minusMinutes(cancelMinutes).isAfter(distributeTime)) {
                return;
            }
            addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("保存标签[5min内取消]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 设置计价器3.0有效使用标签
     * @param addTags
     * @param orderWork
     * @param logType
     */
    private void setQuotationThreeValid(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap){
        try {
            if (Objects.equals(orderWork.getFinalPrice(), GlobalConsts.YES)) {
                return;
            }

            Boolean isValid = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CLICK_CHECK_REPORT, logType)
                    || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_BACK, logType)
                    || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_BACK, logType);
            // 不是点击检测报告不处理
            if (!isValid) {
                return;
            }

            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_WORK_QUOTATION_THREE_VALID);
            // 没有标签配置不处理
            if (Objects.isNull(confOrderTag)) {
                return;
            }

            Integer count = orderTagService.countOrderTagByOrderIdAndTagId(orderWork.getOrderId(), OrderTagConsts.TAG_ID_WORK_QUOTATION_THREE_VALID);
            // 已标记过的不再处理
            if (count > 0) {
                if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_BACK, logType)
                        || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_BACK, logType)) {
                    delTags.add(OrderTagConsts.TAG_ID_WORK_QUOTATION_THREE_VALID);
                }
                return;
            }

            // 不是点击检测报告节点不添加
            if (!Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CLICK_CHECK_REPORT, logType)) {
                return;
            }

            addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("保存标签[计价器3.0有效使用]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 设置计价器3.0成功单有效使用标签
     * @param addTags
     * @param orderWork
     * @param logType
     */
    private void setQuotationThreeSuccessValid(List<OrderTag> addTags, OrderWork orderWork, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap){
        try {

            if (Objects.equals(orderWork.getFinalPrice(), GlobalConsts.YES)) {
                return;
            }

            // 不是收单节点不处理
            if (!Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CHECKOUT, logType)) {
                return;
            }

            // 订单结果不是成功不处理
            if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_SUCCESS)) {
                return;
            }

            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_WORK_QUOTATION_THREE_SUCCESS_VALID);
            // 没有标签配置不处理
            if (Objects.isNull(confOrderTag)) {
                return;
            }

            // 用户未同意不执行
            OrderQuotationProcess orderQuotationProcess = orderQuotationProcessService.findByOrderId(orderWork.getOrderId());
            if (Objects.isNull(orderQuotationProcess) || Objects.isNull(orderQuotationProcess.getAgreeTime())
                    || Objects.equals(orderQuotationProcess.getAgreeStatus(), GlobalConsts.NO)) {
                return;
            }

            Integer count = orderTagService.countOrderTagByOrderIdAndTagId(orderWork.getOrderId(), OrderTagConsts.TAG_ID_WORK_QUOTATION_THREE_SUCCESS_VALID);
            // 已标记过的不再处理
            if (count > 0) {
                return;
            }

            addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("保存标签[计价器3.0有效使用]异常：[{}]", e.getMessage());
        }
    }
    /**
     * 设置一口价有效使用标签
     * @param addTags
     * @param orderWork
     * @param logType
     */
    private void setFinalPriceValid(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap){
        try {

            if (!Objects.equals(orderWork.getFinalPrice(), GlobalConsts.YES)) {
                return;
            }

            Boolean isValid = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CLICK_CHECK_REPORT, logType)
                    || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_BACK, logType)
                    || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_BACK, logType);
            // 不是点击检测报告不处理
            if (!isValid) {
                return;
            }

            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_WORK_FINAL_PRICE_VALID);
            // 没有标签配置不处理
            if (Objects.isNull(confOrderTag)) {
                return;
            }

            Integer count = orderTagService.countOrderTagByOrderIdAndTagId(orderWork.getOrderId(), OrderTagConsts.TAG_ID_WORK_FINAL_PRICE_VALID);
            // 已标记过的不再处理
            if (count > 0) {
                if (Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE_BACK, logType)
                        || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_ASSIGN_BACK, logType)) {
                    delTags.add(OrderTagConsts.TAG_ID_WORK_FINAL_PRICE_VALID);
                }
                return;
            }

            // 不是点击检测报告节点不添加
            if (!Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CLICK_CHECK_REPORT, logType)) {
                return;
            }

            addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
        } catch (Exception e) {
            log.error("保存标签[一口价有效使用]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 设置用户标签
     *
     * @param delTags
     * @param addTags
     * @param orderWork
     * @param orderDetail
     * @param tagMap
     * @param autoFlow 是否自动流转
     */
    private void setUserTag(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Map<Integer, OrderTag> tagMap, int logType, Map<Integer, ConfOrderTag> confOrderTagMap, boolean autoFlow) {

        // 不是自动流转
        if (!autoFlow) {
            boolean isUpdateTag = Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_UPDATE, logType)
                    || Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CONFIRM, logType);
            if (!isUpdateTag) {
                return;
            }
        }

        // 高价值用户
        if (NumberUtil.isNullOrZero(orderWork.getUserId())) {
            return;
        }

        if (Objects.equals(orderDetail.getVvip(), GlobalConsts.YES)) {
            return;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_HIGH_VALUE_USER);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        try {
            log.info("工单[{}] 获取用户标签 入参：[{}]", orderWork.getWorkId(), orderWork.getUserId());
            ResponseDTO<List<UserTagInfoDRO>> listResponseDTO = userTagInfoListRemoteService.listByUserId(orderWork.getUserId());
            log.info("工单[{}] 获取用户标签 出参：[{}]", orderWork.getWorkId(), JSON.toJSONString(listResponseDTO));
            List<UserTagInfoDRO> userTagInfoList = listResponseDTO.getData();
            if (CollectionUtils.isEmpty(userTagInfoList)) {
                return;
            }
            boolean isContains = tagMap.containsKey(OrderTagConsts.USER_TAG_ID_HIGH_VALUE) || tagMap.containsKey(OrderTagConsts.TAG_ID_HIGH_VALUE_USER);
            List<Integer> tagIdList = userTagInfoList.stream().map(UserTagInfoDRO::getTagId).collect(Collectors.toList());
            if (tagIdList.contains(OrderTagConsts.USER_TAG_ID_HIGH_VALUE)) {
                // 增加标签
                if (!isContains) {
                    addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
                }
            } else {
                // 删除标签
                if (isContains) {
                    delTags.add(OrderTagConsts.TAG_ID_HIGH_VALUE_USER);
                    delTags.add(OrderTagConsts.USER_TAG_ID_HIGH_VALUE);
                }
            }
        } catch (Exception e) {
            log.error("保存用户标签[高价值用户]异常：[{}]", e.getMessage());
        }
    }

    /**
     * 提前付
     *
     * @param delTags
     * @param addTags
     * @param orderWork
     * @param orderDetail
     * @param tagMap
     * @param logType
     */
    private void setAdvancePayTag(List<Integer> delTags, List<OrderTag> addTags, OrderWork orderWork, OrderDetail orderDetail, Map<Integer, OrderTag> tagMap, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        boolean isAdvancePay = Objects.equals(orderWork.getPrepayStatus(), PayConsts.PAY_STATUS_DONE)
                && Objects.equals(orderWork.getFullPaymentFlag(), GlobalConsts.YES)
                && Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_PAY);

        if (!isAdvancePay) {
            return;
        }

        ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_ADVANCE_PAY);
        if (Objects.isNull(confOrderTag)) {
            return;
        }

        try {
            log.info("#oms#工单={},是否是提前付工单，入参：channelId: {}, cityId:{}, servCategId:{}, showCategId:{}", orderWork.getOrderId(), orderWork.getChannelId(), orderWork.getCityId(), orderWork.getServCategId(), orderWork.getShowCategId());
            PilotCheckQuery build = PilotCheckQuery
                    .builder()
                    .channelId(orderWork.getChannelId())
                    .cityId(orderWork.getCityId())
                    .pilotTypeId(PilotTypeEnum.PAY_ADVANCE.getId())
                    .servCategId(orderWork.getServCategId())
                    .categId(orderWork.getShowCategId())
                    .build();
            ResponseDTO<Boolean> responseDTO = pilotRemoteService.checkPilotByQuery(build);
            log.info("#oms#工单={},是否是提前付工单，出参={}", orderWork.getOrderId(), JSON.toJSONString(responseDTO));

            if (!responseDTO.isSuccess()) {
                log.info("获取用户信息失败，无法更新高价值用户标签, 用户ID：{}", orderWork.getUserId());
                return;
            }

            boolean isContains = tagMap.containsKey(OrderTagConsts.TAG_ID_ADVANCE_PAY);
            if (!responseDTO.getData()) {
                // 删除标签
                if (isContains) {
                    delTags.add(OrderTagConsts.TAG_ID_ADVANCE_PAY);
                }
            } else {
                // 增加标签
                if (!isContains) {
                    addTags.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
                }
            }
        } catch (Exception e) {
            log.error("保存用户标签[提前付]异常：[{}]", e.getMessage());
        }
    }

    private OrderTag getOrderTag(Long orderId, Long workId, ConfOrderTag confOrderTag) {
        OrderTag orderTag = new OrderTag();
        orderTag.setOrderId(orderId);
        orderTag.setWorkId(workId);
        orderTag.setTagType(OrderTagConsts.ORDER_TAG_USER_SYSTEM);
        orderTag.setTagId(confOrderTag.getId());
        orderTag.setTagName(confOrderTag.getTagName());
        orderTag.setCategoryIds(confOrderTag.getCategoryIds());
        orderTag.setCreater(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
        orderTag.setUpdater(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM));

        return orderTag;
    }

    /**
     * 添加订单标签
     *
     * @param orderTagAddDTO
     * @throws OmsBaseException
     */
    @Override
    public void addOrderTag(OrderTagAddDTO orderTagAddDTO) throws OmsBaseException {
        Objects.nonNull(orderTagAddDTO.getOrderId());
        Objects.nonNull(orderTagAddDTO.getWorkId());

        if (CollectionUtil.isNullOrEmpty(orderTagAddDTO.getTagIdList())) {
            throw new OmsBaseException("标签ID集合不能为空");
        }
        // 添加去重
        List<Integer> tagIdList = orderTagAddDTO.getTagIdList().stream().distinct().collect(Collectors.toList());

        // 标记配置
        List<ConfOrderTag> confOrderTagList = confOrderTagService.findConfByIdList(tagIdList);
        Map<Integer, ConfOrderTag> confOrderTagMap = confOrderTagList.stream().collect(Collectors.toMap(ConfOrderTag::getId, item -> item, (k1, k2) -> k1));

        // 查询订单已有标签
        List<OrderTag> orderTags = orderTagService.listOrderTagByOrderId(orderTagAddDTO.getOrderId(), orderTagAddDTO.getWorkId());
        Map<Integer, OrderTag> orderTagMap = orderTags.stream().collect(Collectors.toMap(OrderTag::getTagId, e -> e, (v1, v2) -> v1));

        // 有效联系与无效联系不兼容，如果有 有效联系，需要删除无效联系
        if (tagIdList.contains(OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE)) {
            boolean isExist = orderTags.stream().anyMatch(m -> m.getTagId().equals(OrderTagConsts.TAG_ID_WORK_CONTACT_INVALID));
            if (isExist) {
                OrderTagDelDTO orderTagDelDTO = new OrderTagDelDTO();
                orderTagDelDTO.setOrderId(orderTagAddDTO.getOrderId());
                orderTagDelDTO.setWorkId(orderTagAddDTO.getWorkId());
                orderTagDelDTO.setOrderTagIdList(Lists.newArrayList(OrderTagConsts.TAG_ID_WORK_CONTACT_INVALID));
                Integer integer = orderTagService.deleteOrderTagByTagIdList(orderTagDelDTO);
                // 删除无效标签是否成功：
                log.info("删除无效标签是否成功:{}",integer);
            }
        }

        List<OrderTag> addTagList = Lists.newArrayListWithCapacity(orderTagAddDTO.getTagIdList().size());
        Date now = DateUtil.getNow();
        tagIdList.forEach(id -> {
            ConfOrderTag confOrderTag = confOrderTagMap.get(id);
            if (Objects.isNull(confOrderTag)) {
                return;
            }
            // 去重 将库里没有的标签，添加进去
            if (Objects.isNull(orderTagMap.get(id))) {
                OrderTag orderTag = new OrderTag();
                orderTag.setOrderId(orderTagAddDTO.getOrderId());
                orderTag.setWorkId(orderTagAddDTO.getWorkId());
                orderTag.setTagType(OrderTagConsts.ORDER_TAG_USER_SYSTEM);
                orderTag.setTagId(confOrderTag.getId());
                orderTag.setTagName(confOrderTag.getTagName());
                orderTag.setCategoryIds(confOrderTag.getCategoryIds());
                orderTag.setCreater(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                orderTag.setUpdater(GlobalConsts.getOperatorTypeName(GlobalConsts.OPERATE_USER_TYPE_SYSTEM));
                // 有效标签存放标记时间
                if(Objects.equals(orderTag.getTagId(),OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE) && Objects.nonNull(orderTagAddDTO.getContactTime())){
                    orderTag.setCreateTime(orderTagAddDTO.getContactTime());
                } else {
                    orderTag.setCreateTime(now);
                }
                orderTag.setUpdateTime(now);
                addTagList.add(orderTag);
            }
        });
        if (CollectionUtil.isNullOrEmpty(addTagList)) {
            return;
        }
        //orderTagService.saveOrderTagListBatch(addTagList);

        OrderTagDTO orderTagDTO = new OrderTagDTO();
        orderTagDTO.setOrderId(orderTagAddDTO.getOrderId());
        orderTagDTO.setWorkId(orderTagAddDTO.getWorkId());
        orderTagDTO.setOrderTagList(addTagList);
        orderTagService.saveOrderTagList(orderTagDTO);

        this.sendOrderTagNotice(orderTagDTO);
    }

    @Override
    public void autoAddOrderTag(OrderWork orderWork) {

        List<OrderTag> addTagList = Lists.newArrayList();

        // 查询工单标签信息
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKeySrcMaster(orderWork.getOrderId());

        Map<Integer, OrderTag> tagMap = Maps.newHashMap();

        // 标记配置
        List<ConfOrderTag> confOrderTagList = confOrderTagService.listByQuery(ConfOrderTagQuery.builder().build());
        Map<Integer, ConfOrderTag> confOrderTagMap = confOrderTagList.stream().collect(Collectors.toMap(ConfOrderTag::getId, item -> item, (k1, k2) -> k1));

        // 用户标签
        this.setUserTag(null, addTagList, orderWork, orderDetail, tagMap, 0, confOrderTagMap, true);

        // 优质订单
        this.setHighQualityOrder(null, addTagList, orderWork, orderDetail, 0, tagMap, confOrderTagMap, true);

        // 无网格
        this.setNonGridTag(null, addTagList, orderWork, orderDetail, 0, tagMap, confOrderTagMap, true);

        if (CollectionUtil.isNotNullOrEmpty(addTagList)) {
            OrderTagDTO orderTagDTO = new OrderTagDTO();
            orderTagDTO.setOrderId(orderWork.getOrderId());
            orderTagDTO.setWorkId(orderWork.getWorkId());
            orderTagDTO.setOrderTagList(addTagList);
            orderTagService.saveOrderTagList(orderTagDTO);
        }

        // 如果标签发生变动发送tag的通用消息
        if (CollectionUtil.isNotNullOrEmpty(addTagList)) {
            OrderTagDTO orderTagDTO = new OrderTagDTO();
            orderTagDTO.setOrderId(orderWork.getOrderId());
            orderTagDTO.setWorkId(orderWork.getWorkId());
            this.sendOrderTagNotice(orderTagDTO);
        }
    }

    /**
	 * 检查工单是否有指定的标签分类
	 *
	 * @param orderId
	 * @param workId
	 * @param categoryId 标签分类id
	 * @return
	 */
    @Override
    public Boolean existsCategoryTagByCategoryId(Long orderId, Long workId, Integer categoryId) {
        Objects.requireNonNull(categoryId, "标签分类ID不能为空");

        // 查询工单标签信息
        List<OrderTag> orderTags = orderTagService.listOrderTagByOrderId(orderId, workId);
        if (CollectionUtils.isEmpty(orderTags)) {
            return false;
        }

        String categoryIdStr = String.valueOf(categoryId);
        Boolean isExists = orderTags.stream().anyMatch(orderTag ->
                StringUtils.isNotBlank(orderTag.getCategoryIds())
                        && Arrays.asList(orderTag.getCategoryIds().split(",")).contains(categoryIdStr));

        log.info("OrderTagBServiceImpl#existsCategoryTagByCategoryId 检查工单排除工程师绩效标签 接口出参：【isExists：{}】", isExists);
        return isExists;
    }


    @Override
    public void sendOrderTagMq(Long orderId, Long workId, Integer logType) {

        // 如果订单日志类型是点击检测报告需要生成标签
        if (Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_CLICK_CHECK_REPORT)) {
            String key = String.format("tag-%s-%s", workId, DateUtil.getNowTimestamp());
            JSONObject jb = new JSONObject();
            jb.put("orderId", orderId);
            jb.put("workId", workId);
            jb.put("logType", logType);
            String content = jb.toJSONString();

            log.info("订单标签同步队列， key:{}, content:{}", key, content);
            zmnMQSender.send(MqTopicConsts.ZMN_TOPIC_OMS, MessageQueueTagConsts.ORDER_TAG, key, content);
        }
    }

    /**
     * 类描述：指定时间内， 派给工程师的同用户的订单中，是否有有效联系
     *
     * @author  liuying
     * @date   2022/05/05 12:45
     */
    @Override
    public boolean existContactEffectiveTagOrderByExcludeOrderId(Long orderId, Long workId) {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(orderId, workId);
        OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(orderId);
        return this.existContactEffectiveTagOrderByExcludeOrderId(orderWork, orderDetail);
    }

    private boolean existContactEffectiveTagOrderByExcludeOrderId(OrderWork orderWork, OrderDetail orderDetail) {
        Integer oneTwoTypeId = baseCodeService.getOneTwoTypeId(com.zmn.consts.GlobalConsts.PLAT_MARK_ZMN,
                OrderBaseCodeMapConsts.CODE_MAX_EFFECTIVE_CONTACT_TIME);
        if (oneTwoTypeId == null) {
            return false;
        }

        Date contactTime = Optional.ofNullable(orderWork.getContactTime()).orElse(DateUtil.getNow());

        int workRelationTime = -1 * oneTwoTypeId;
        Date baseDefer = DateUtil.getBaseDefer(contactTime, workRelationTime);

        // 任一电话匹配
        List<String> phoneList = Lists.newArrayList(orderDetail.getTelephone());
        if (StringUtils.isNotBlank(orderDetail.getTelephone2())) {
            phoneList.add(orderDetail.getTelephone2());
        }
        if (StringUtils.isNotBlank(orderDetail.getTelephone3())) {
            phoneList.add(orderDetail.getTelephone3());
        }

        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                // 排除自己
                .mustNot(QueryBuilders.termQuery("id", orderWork.getWorkId()))
                .filter(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)))
                // 工程师ID
                .filter(QueryBuilders.termQuery("masterId", orderWork.getMasterId()))
                // 联系时间
                .filter(QueryBuilders.rangeQuery("contactTime").gte(DateUtil.dateFormatToString(baseDefer, DateUtil.FORMAT_DEFAULT))
                        .lte(DateUtil.dateFormatToString(contactTime, DateUtil.FORMAT_DEFAULT)))
                // 联系电话
                .filter(QueryBuilders.termsQuery("contact.phone", orderEncryptService.encrypt(phoneList)))
                // 有效联系
                .filter(QueryBuilders.termQuery("orderTagList.tagId", OrderTagConsts.TAG_ID_WORK_CONTACT_EFFECTIVE));

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        NativeSearchQuery build = nativeSearchQueryBuilder.withQuery(queryBuilder)
                .build();
        long count = orderWorkEsBService.countByQuery(build);
        log.info("工单{} 查询有效联系订单数量：{} , contactTime={}~{}", orderWork.getWorkId(), count,
                DateUtil.dateFormatToString(baseDefer, DateUtil.FORMAT_DEFAULT), DateUtil.dateFormatToString(contactTime, DateUtil.FORMAT_DEFAULT));
        return count > 0;
    }

    /**
     * 相似当日派标签处理
     * @param delTagList
     * @param addTagList
     * @param orderWork
     * @param orderDetail
     * @param logType
     * @param tagMap
     * @param confOrderTagMap
     */
    private void setSimilarDistributeTag(List<Integer> delTagList, List<OrderTag> addTagList, OrderWork orderWork, OrderDetail orderDetail, Integer logType, Map<Integer, OrderTag> tagMap, Map<Integer, ConfOrderTag> confOrderTagMap) {
        // 非派单节点不处理
        if (!Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_DISTRIBUTE, logType)) {
            return;
        }

        try {
            OrderTag similarDistributeTag = tagMap.get(OrderTagConsts.TAG_ID_SIMILAR_TODAY_DISTRIBUTE);
            // 查询工单最后一次派单数据
            OrderChangeRecord record = orderChangeRecordService.getChangeRecordByOrderIdSrcMaster(orderWork.getOrderId());
            if (Objects.isNull(record)) {
                log.warn("订单[{}]修改记录为空", orderWork.getOrderId());
                return;
            }
            // 最后一次派单规则 非已派相似 如果原本有 OrderTagConsts.TAG_ID_SIMILAR_TODAY_DISTRIBUTE 需删除
            if (!Objects.equals(record.getLastDistributeRule(), OrderDistributeConsts.DISTRIBUTE_RULE_SIMILAR)) {
                if (Objects.nonNull(similarDistributeTag)) {
                    delTagList.add(similarDistributeTag.getTagId());
                }
                return;
            }

            // 参考  com.zmn.oms.zmn.business.impl.work.customwork.ZsDistributeWorkBServiceImpl.getDistributedSimilarWorkIdList
            // 查询当日派单是否存在相似订单
            // 预约时间 或 经纬度为空 则为不相似单
            Double latitude = orderDetail.getLatitude();
            Double longitude = orderDetail.getLongitude();
            Date dutyTime = orderWork.getDutyTime();
            Date distributeTime = orderWork.getDistributeTime();

            if (Objects.isNull(latitude) || Objects.isNull(longitude) || Objects.isNull(dutyTime)) {
                return;
            }

            // region 查询条件
            // 相似订单需要与当前订单条件
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

            // 状态结果：已派单-已领单-已上门-服务完成 / 进行中
            boolQueryBuilder.must(QueryBuilders.termsQuery("status",
                    Lists.newArrayList(OrderStatusConsts.WORK_STATUS_DISTRIBUTE, OrderStatusConsts.WORK_STATUS_TAKE, OrderStatusConsts.WORK_STATUS_VISIT, OrderStatusConsts.WORK_STATUS_SERVICE_COMPLETE)));
            boolQueryBuilder.must(QueryBuilders.termQuery("resultStatus", OrderStatusConsts.WORK_RESULT_DOING));

            // 新单，返修单
            boolQueryBuilder.must(QueryBuilders.termsQuery("type", Lists.newArrayList(OrderConsts.ORDER_TYPE_NEW, OrderConsts.ORDER_TYPE_REWORK)));

            // 订单距离 <= 2KM
            boolQueryBuilder.must(QueryBuilders.geoDistanceQuery("contact.location").distance("2km").point(latitude, longitude));

            // 用户电话
            List<String> phoneList = Lists.newArrayListWithCapacity(3);
            if (StringUtils.isNotBlank(orderDetail.getTelephone())) {
                phoneList.add(orderDetail.getTelephone());
            }
            if (StringUtils.isNotBlank(orderDetail.getTelephone2())) {
                phoneList.add(orderDetail.getTelephone2());
            }
            if (StringUtils.isNotBlank(orderDetail.getTelephone3())) {
                phoneList.add(orderDetail.getTelephone3());
            }

            if (CollectionUtils.isNotEmpty(phoneList)) {
                boolQueryBuilder.must(QueryBuilders.termsQuery("contact.phone", orderEncryptService.encrypt(phoneList)));
            }

            // 派单时间同一天
            String startTimeStr = DateUtil.toString(DateUtil.getDateStart(distributeTime));
            String endTimeStr = DateUtil.toString(DateUtil.getDateEnd(distributeTime));
            boolQueryBuilder.must(QueryBuilders.rangeQuery("distributeTime").gte(startTimeStr).lte(endTimeStr));

            // 包含工程师条件 （可选）
            boolQueryBuilder.must(QueryBuilders.termQuery("masterId", orderWork.getMasterId()));

            // 排除当前订单
            boolQueryBuilder.mustNot(QueryBuilders.termQuery("orderId", orderWork.getOrderId()));

            // region 构建查询对象
            NativeSearchQuery searchQuery = new NativeSearchQuery(boolQueryBuilder);
            searchQuery.setPageable(PageRequest.of(0, 100));
            String[] columns = {"id"};
            SourceFilter sourceFilter = new FetchSourceFilter(columns, null);
            searchQuery.addSourceFilter(sourceFilter);

            List<EsOrderWork> esOrderWorks = orderWorkEsBService.listPageByQuery(searchQuery);

            // 不存在相似当天派的订单结束
            if (CollectionUtil.isNullOrEmpty(esOrderWorks)) {
                return;
            }
            log.info("存在相似当天派的订单:[{}]", esOrderWorks);

            if (Objects.isNull(similarDistributeTag)) {
                addTagList.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTagMap.get(OrderTagConsts.TAG_ID_SIMILAR_TODAY_DISTRIBUTE)));
            }
        } catch (Exception e) {
            log.error("相似当日派标签处理出现异常：{}", e);
        }
    }

    /**
     * 疫情无法服务处理
     * @param addTagList
     * @param orderWork
     * @param logType
     * @param confOrderTagMap
     */
    private void setEpidemicUnserviceableCancel(List<OrderTag> addTagList, OrderWork orderWork, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap) {
        try {
            if (!Objects.equals(OrderLogConsts.ORDER_LOG_TYPE_CANCEL, logType)) {
                return;
            }
            // 未取消的不处理
            if (Objects.isNull(orderWork.getCancelTime())) {
                return;
            }

            // 没有指定标签配置-结束
            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_EPIDEMIC_UNSERVICEABLE_CANCEL);
            if (Objects.isNull(confOrderTag)) {
                return;
            }

            // 查询订单取消的缘由 -- 注意：目前取消备注 一个工单只有一条
            OrderRemarkVO remarkVO = orderRemarkBService.findOrderRemarkVO(orderWork.getOrderId(), orderWork.getWorkId(), OrderConsts.ORDER_REMARK_TYPE_CANCEL);
            if (Objects.isNull(remarkVO) || CollectionUtil.isNullOrEmpty(remarkVO.getDetailVOList())) {
                log.warn("工单[{}]未查询到取消备注", orderWork.getWorkId());
                return;
            }

            // 只匹配 疫情无法服务 OrderConsts.CANCEL_REASON_EPIDEMIC_UNSERVICEABLE_ID
            Integer mapId = remarkVO.getDetailVOList().get(0).getMapId();
            if (Objects.equals(mapId, OrderConsts.CANCEL_REASON_EPIDEMIC_UNSERVICEABLE_ID)) {
                addTagList.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));
            }

        } catch (Exception e) {
            log.error("保存标签[疫情无法服务]异常：[{}]", e.getMessage());
        }
    }

    private void processQuoteUnConfirm(List<Integer> delTagList, List<OrderTag> addTagList, OrderWork orderWork, Integer logType, Map<Integer, ConfOrderTag> confOrderTagMap, Map<Integer, OrderTag> tagMap) {
        try {
            // 没有指定标签配置-结束
            ConfOrderTag confOrderTag = confOrderTagMap.get(OrderTagConsts.TAG_ID_QUOTE_UN_CONFIRMED);
            if (Objects.isNull(confOrderTag)) {
                return;
            }
            // 下单
            if (!Objects.equals(logType, OrderLogConsts.ORDER_LOG_TYPE_INPUT)) {
                return;
            }
            // 是否返修新单
            boolean isReworkNew = Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW)
                    && Objects.equals(orderWork.getChannelId(), OrderConsts.CHANNEL_ID_PLAT_REWORK_NEW_ORDER)
                    &&  NumberUtil.isNotNullOrZero(orderWork.getOriginalId());

            if (!Objects.equals(orderWork.getType(), OrderConsts.ORDER_TYPE_NEW) || isReworkNew) {
                return;
            }
            if (NumberUtil.isNotNullOrZero(orderWork.getProductId()) && NumberUtil.isNotNullOrZero(orderWork.getOriginalAmount())) {
                return;
            }
            
            // 提前报价试点
            AdvanceQuoteOpenQuery advanceQuoteOpenQuery = AdvanceQuoteOpenQuery.builder()
                    .cityId(orderWork.getCityId())
                    .servCategId(orderWork.getServCategId())
                    .showProductType(NumberUtil.isNotNullOrZero(orderWork.getProductId()) ? BaseProductConsts.ERP_SHOW_TYPE : BaseProductConsts.EC_SHOW_TYPE)
                    .productId(NumberUtil.isNotNullOrZero(orderWork.getProductId()) ? orderWork.getProductId() : orderWork.getShowProductId())
                    .build();
            boolean openAdvanceQuote = baseCodeService.isOpenAdvanceQuote(advanceQuoteOpenQuery);
            if (!openAdvanceQuote) {
                return;
            }
            
            // 新增标签
            addTagList.add(this.getOrderTag(orderWork.getOrderId(), orderWork.getWorkId(), confOrderTag));

        } catch (Exception e) {
            log.info("处理下单未报价失败");
        }
    }
}
